package com.jeeplus.modules.web.wx;

import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.CacheObj;
import cn.hutool.cache.impl.TimedCache;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.lang.Tuple;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.PageUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Maps;
import com.google.common.collect.Table;
import com.jeeplus.common.json.AjaxJson;
import com.jeeplus.common.room.Room;
import com.jeeplus.common.utils.StringUtils;
import com.jeeplus.common.utils.number.NumberUtil;
import com.jeeplus.core.web.BaseController;
import com.jeeplus.modules.sys.entity.User;
import com.jeeplus.modules.web.entity.YJRoomUser;
import com.jeeplus.modules.web.entity.YjScoreRecord;
import com.jeeplus.modules.web.entity.wx.YsUser;
import com.jeeplus.modules.web.mapper.WxUserMapper;
import com.jeeplus.modules.web.mapper.YJRoomUserMapper;
import com.jeeplus.modules.web.mapper.YjScoreRecordMapper;
import com.jeeplus.modules.web.service.YjScoreRecordService;
import com.jeeplus.modules.web.socket.UserMsgSocket;
import org.javatuples.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.StampedLock;
import java.util.stream.Collectors;

/**
 * @author 十戒丶
 * @date 2021-01-21 21:34:26
 */
@Controller
@RequestMapping(value = "/wx/score_record")
public class YjScoreRecordController extends BaseController {
    /**
     * tuple    存  房间id
     * map      存 需要帮记人，状态 0 需要帮记 1 同意帮记 2 不同意帮记 3 取消帮记
     * 60*1000    1分钟查询一次
     */
    public static volatile TimedCache<Pair<String, String>, List<Table<String, YsUser, Integer>>> helpNotesCache = CacheUtil.newTimedCache(24 * 60 * 60 * 1000);
    private static final StampedLock lock = new StampedLock();

    static {
        new ScheduledThreadPoolExecutor(1, r -> ThreadUtil.newThread(r, "帮记检查")).scheduleAtFixedRate(() -> {
            final long stamp = lock.writeLock();
            try {
                final Iterator<CacheObj<Pair<String, String>, List<Table<String, YsUser, Integer>>>> cacheObjIterator = helpNotesCache.cacheObjIterator();
                if (cacheObjIterator.hasNext()) {
                    final CacheObj<Pair<String, String>, List<Table<String, YsUser, Integer>>> next = cacheObjIterator.next();
                    final Pair<String, String> key = next.getKey();
                    if (helpNotesCache.get(key) == null || helpNotesCache.get(key).isEmpty()) {
                        helpNotesCache.remove(key);
                    }
                }
            } finally {
                lock.unlockWrite(stamp);
            }
        }, 60 * 1000, 60 * 1000, TimeUnit.MILLISECONDS);
        helpNotesCache.schedulePrune(5 * 60 * 1000);
    }

    private static final Logger log = LoggerFactory.getLogger(YjScoreRecordController.class);
    @Autowired
    YjScoreRecordMapper yjScoreRecordMapper;
    @Autowired
    YJRoomUserMapper yjRoomUserMapper;
    @Autowired
    WxUserMapper wxUserMapper;
    @Autowired
    YjScoreRecordService yjScoreRecordService;

    /**
     * 获取每个人的总分
     *
     * @return
     */
    @RequestMapping("/getTotal")
    @ResponseBody
    public Map<String, Object> getTotal(String openId, String roomFlag, String roomNumber) {

        long start = System.currentTimeMillis();

        //long jushustart = System.currentTimeMillis();
        //局数
        List<YjScoreRecord> gameCount = yjScoreRecordMapper.findCount(roomFlag, roomNumber, 0, 5);
        //long jushuEnd = System.currentTimeMillis();
        // logger.info("getTotal--获取局数总耗时："+(jushuEnd - jushustart) + "ms");

        // long taifeistart = System.currentTimeMillis();
        //台费
        List<YjScoreRecord> scoreRecordList = yjScoreRecordMapper.getCostTotal(roomFlag, roomNumber, 0, 5);
        //long taifeiend = System.currentTimeMillis();
        //logger.info("getTotal--获取每局台费总耗时："+(taifeiend - taifeistart) + "ms");

        //long zongtaifeistart = System.currentTimeMillis();
        List<YjScoreRecord> costList = yjScoreRecordMapper.getCostTotalByRoom(roomFlag, roomNumber);
        //long zongtaifeiend = System.currentTimeMillis();
        //logger.info("getTotal--获取总台费总耗时："+(zongtaifeiend - zongtaifeistart) + "ms");

        YJRoomUser yjRoomUser = new YJRoomUser();
        yjRoomUser.setRoomUser("台费");
        if (costList.get(0) != null && costList.size() > 0) {
            yjRoomUser.setTotalScore(costList.get(0).getGameCost());
        } else {
            yjRoomUser.setTotalScore("0");
        }
        if (scoreRecordList != null && scoreRecordList.size() > 0) {
            yjRoomUser.setList(gameCount);
        } else {
           /* YjScoreRecord yjScoreRecord = new YjScoreRecord();
            yjScoreRecord.set
            yjScoreRecord.setRemarks("");*/
            yjRoomUser.setList(new ArrayList<>());
        }

        //long renstart = System.currentTimeMillis();
        //人员
        List<YJRoomUser> roomUserList = yjRoomUserMapper.findUserByFlagAndNum(roomNumber, roomFlag);
        //long renend = System.currentTimeMillis();
        // logger.info("getTotal--获取每个房间人数总耗时："+(renend - renstart) + "ms");

        for (int index = 0, length = roomUserList.size(); index < length; index++) {
            if (openId.equals(roomUserList.get(index).getRoomUser())) {
                YJRoomUser temp = roomUserList.get(0);
                roomUserList.set(0, roomUserList.get(index));
                roomUserList.set(index, temp);
            }
        }

        //long mrenstart = System.currentTimeMillis();
        //获取每个人总分
        //List<YjScoreRecord> totalUserList = yjScoreRecordMapper.scoreTotal(roomFlag, roomNumber);

        List<YjScoreRecord> totalUserList = yjScoreRecordMapper.scoreTotalS(roomFlag, roomNumber);


        //long mrenend = System.currentTimeMillis();
        // logger.info("getTotal--获取每个人总分总耗时："+(mrenend - mrenstart) + "ms");
        //局数
        List<YjScoreRecord> gameCountList = new ArrayList<>();
        //yjScoreRecordMapper.getCostTotal(roomFlag, roomNumber);
        if (scoreRecordList.size() > 0) {
            //取五条
            gameCountList = scoreRecordList.subList(0, Math.min(scoreRecordList.size(), 5));
        }
        //long mrenmeijustart = System.currentTimeMillis();
        for (YJRoomUser user : roomUserList) {
            if (totalUserList.size() > 0) {
                boolean bool = totalUserList.stream().anyMatch(a -> a.getRoomUser().equals(user.getRoomUser()));
                if (bool) {
                    for (YjScoreRecord record : totalUserList) {
                        if (record.getRoomUser().equals(user.getRoomUser())) {
                            user.setTotalScore(record.getScore());
                        }
                    }
                } else {
                    user.setTotalScore("0");
                }


                //获取每人所有局分数
                List<YjScoreRecord> userRecordList = yjScoreRecordMapper.getScoreDetailS(user.getRoomFlag(), user.getRoomNum(), user.getRoomUser(), "", 0, 5);

                List<YjScoreRecord> scoreUList = new ArrayList<>();
                for (YjScoreRecord record : gameCountList) {
                    //获取每人每局对应分数
                    List<YjScoreRecord> scoreUserList = userRecordList.stream().filter(userRecord -> userRecord.getGamesCount().equals(record.getGamesCount())).collect(Collectors.toList());
                    // yjScoreRecordMapper.getScoreDetail(user.getRoomFlag(), user.getRoomNum(), user.getRoomUser(), record.getGamesCount());

                    if (scoreUserList.size() > 0) {
                        scoreUList.add(scoreUserList.get(0));
                    } else {
                        YjScoreRecord recordw = new YjScoreRecord();
                        recordw.setRoomNum(user.getRoomNum());
                        recordw.setGamesCount(record.getGamesCount());
                        recordw.setScore("0");
                        recordw.setRoomUser(user.getRoomUser());
                        recordw.setRoomFlag(user.getRoomFlag());
                        scoreUList.add(recordw);
                    }
                }
                user.setList(scoreUList);

            } else {
                user.setList(new ArrayList<>());
                user.setTotalScore("0");
            }
            user.getList().stream().sorted(Comparator.comparing(YjScoreRecord::getGamesCount))
                    .collect(Collectors.toList());
        }
        //long mrenmeijuend = System.currentTimeMillis();
        //logger.info("getTotal--获取每个人每局分数总耗时："+(mrenmeijuend - mrenmeijustart) + "ms");
        Map<String, Object> map = new HashMap<String, Object>();
        if (!roomUserList.isEmpty()) {
            for (int i = 0; i < roomUserList.size(); i++) {
                if (StrUtil.isEmpty(roomUserList.get(i).getUserName())) {
                    roomUserList.get(i).setUserName(Room.ROMM_TYEP_MAP.get(roomUserList.get(i).getRoomUser() + roomNumber));

                }

            }
        }

        if (roomUserList.size() > 0) {
            map.put("gameCount", gameCount);
            map.put("gameCost", yjRoomUser);
            map.put("success", true);
            map.put("user", roomUserList);
        } else {
            map.put("success", false);
            map.put("list", scoreRecordList);
        }
        long end = System.currentTimeMillis();
        logger.info("getTotal--获取每人分数统计总耗时：" + (end - start) + "ms");

        return map;
    }

    /* */

    /**
     * 获取每局的积分
     *
     * @return
     *//*
    @RequestMapping("/getScoreDetail")
    @ResponseBody
    public  Map<String, Object> getScoreDetail(String roomFlag, String roomNumber) {
        Table<String, String, String> table = HashBasedTable.create();
        Map<String, Object> map = new HashMap<String, Object>();

       //获取头像
        List<YjScoreRecord> images = yjScoreRecordMapper.findUrl(roomFlag, roomNumber);
        for(YjScoreRecord image : images){
            if(image.getUserUrl() == null || image.equals("")){
                image.setUserUrl("0");
            }
        }
        //获取每局的台费
        List<YjScoreRecord> costList = yjScoreRecordMapper.getCostTotal(roomFlag, roomNumber);
        for (YjScoreRecord record : scoreRecordList) {
            for (YjScoreRecord cost : costList) {
                if (record.getGamesCount().equals(cost.getGamesCount())) {
                    table.put(record.getGamesCount(), "台费", cost.getGameCost());
                }
            }
            table.put(record.getGamesCount(), record.getRoomUser(), record.getScore());
        }
        map.put("images",images);
        map.put("table",table.cellSet());
        return map;
    }
    */
    @ResponseBody
    @PostMapping(value = "saveScore")
    public AjaxJson saveScore(HttpServletRequest request, @RequestBody Dict param) throws IOException {
        TimeInterval interval = DateUtil.timer();
        TimeInterval intervalTest = DateUtil.timer();
        final LinkedHashMap<String, Object> linkedHashMap = Maps.newLinkedHashMap();
        AjaxJson ajaxJson = new AjaxJson();
        String openId = param.getStr("openId");
        logger.info("saveScore:{}:保存分数开始", openId);
        //参数：房间唯一标识，房间号，牌局，台费，【{玩家，积分}】
        if (StringUtils.isBlank(openId)) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("用户为空");
            return ajaxJson;
        }
        //玩家和自己的唯一键不一样为帮记
        final String gamesCount = StrUtil.isBlank(param.getStr("gamesCount")) ? null : param.getStr("gamesCount");
        if (gamesCount == null || !NumberUtil.isNumber(gamesCount)) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("牌局数异常");
            return ajaxJson;
        }
        linkedHashMap.put("gamesCount", NumberUtil.isNumber(gamesCount) ? NumberUtil.toInt(gamesCount) : null);
        AtomicReference<String> roomNum = new AtomicReference<>();
        final String roomFlag = StrUtil.isBlank(param.getStr("roomFlag")) ? null : param.getStr("roomFlag");
        if (StringUtils.isBlank(roomFlag)) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("房间参数为空");
            return ajaxJson;
        }
        //查询房间玩家
        final Map<String, String> roomUsers = yjRoomUserMapper.findByRoomFlagAndIsOut("0", roomFlag)
                .stream()
                .peek(v1 -> {
                    roomNum.set(v1.getRoomNum());
                })
                .collect(LinkedHashMap::new, (m, v) -> m.put(v.getRoomUser(), null), LinkedHashMap::putAll);
        if (roomUsers.isEmpty()) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("房间不存在");
            return ajaxJson;
        }
        logger.info("saveScore:{}: 到查询房间用时：{}", openId, intervalTest.intervalRestart());
        String gameCost = StrUtil.isBlank(param.getStr("gameCost")) ? "0" : param.getStr("gameCost");
        final List<YjScoreRecord> yjScoreRecords = (param.get("infos") == null ? null : Convert.toList(Dict.class, param.get("infos")))
                .stream()
                .map(v1 -> {
                    YjScoreRecord yjScoreRecord = new YjScoreRecord();
                    yjScoreRecord.setRoomNum(roomNum.get());
                    yjScoreRecord.setRoomFlag(roomFlag);
                    yjScoreRecord.setRoomUser(v1.getStr("roomUser"));
                    if (openId.equals(v1.get("roomUser"))) {
                        yjScoreRecord.setGameCost(gameCost);
                    } else {
                        yjScoreRecord.setGameCost("0");
                    }
                    yjScoreRecord.setScore(StrUtil.isBlank(v1.getStr("score")) ? "0" : v1.getStr("score"));
                    yjScoreRecord.setGamesCount(gamesCount);
                    return yjScoreRecord;
                })
                .collect(Collectors.toList());
        if (yjScoreRecords.stream()
                .filter(v1 -> StringUtils.isBlank(v1.getRoomUser()) || !roomUsers.containsKey(v1.getRoomUser()))
                .filter(v1 -> !NumberUtil.isNumber(v1.getScore()))
                .filter(v1 -> !NumberUtil.isNumber(v1.getGameCost()))
                .findAny()
                .orElse(null) != null) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("提交参数异常");
            return ajaxJson;
        }
        yjScoreRecords.forEach(
                v1 ->
                        roomUsers.put(v1.getRoomUser(),
                                NumberUtil.toString(NumberUtil.toInt(v1.getScore()) + NumberUtil.toInt(v1.getGameCost())))
        );
        final List<YjScoreRecord> saveInfos = yjScoreRecordService.findByRoomFlagAndGamesCount(roomFlag, gamesCount)
                .stream()
                .peek(v1 -> {
                    if (roomUsers.get(v1.getRoomUser()) == null) {
                        //这边会加上台费
                        roomUsers.put(v1.getRoomUser(), NumberUtil.toString(NumberUtil.toInt(v1.getScore()) + NumberUtil.toInt(v1.getGameCost())));
                    }
                })
                .collect(Collectors.toList());
        logger.info("saveScore:{}:到查询得分用时：{}", openId, intervalTest.intervalRestart());
        if (roomUsers.containsValue(null)) {
            logger.info("数据还未填完");
            final int sum = roomUsers.values().stream().mapToInt(NumberUtil::toInt).sum();
            if (sum != 0) {
                ajaxJson.setSuccess(false);
                ajaxJson.setErrorCode("0");
                ajaxJson.setMsg(String.valueOf(sum));
                return ajaxJson;
            }
        } else {
            final int sum = roomUsers.values().stream().mapToInt(NumberUtil::toInt).sum();
            if (sum != 0) {
                ajaxJson.setSuccess(false);
                ajaxJson.setErrorCode("0");
                ajaxJson.setMsg(String.valueOf(sum));
                return ajaxJson;
            } else {
                yjRoomUserMapper.updateEndGamesCountByRoomFlag(roomFlag, StrUtil.isBlank(gamesCount) ? "1" : gamesCount);
                linkedHashMap.put("gamesCount", NumberUtil.isNumber(gamesCount) ? NumberUtil.toInt(gamesCount) + 1 : null);
                yjScoreRecordService.socketPutNextGame(openId, roomFlag, NumberUtil.toInt(gamesCount) + 1);
            }
        }
        for (YjScoreRecord scoreRecord : yjScoreRecords) {
            final YjScoreRecord yjScoreRecord1 = saveInfos.stream().filter(v1 -> scoreRecord.getRoomUser().equals(v1.getRoomUser())).findAny().orElse(null);
            //登录的不等于记录的，为带记
            if (!StringUtils.equals(scoreRecord.getRoomUser(), openId)) {
                scoreRecord.setIsHelpRecord(1);
                scoreRecord.setUpdateBy(new User(openId));
            } else {
                scoreRecord.setCreateBy(new User(openId));
            }
            if (yjScoreRecord1 == null) {
                yjScoreRecordService.save(scoreRecord);
            } else {
                yjScoreRecord1.setScore(scoreRecord.getScore());
                yjScoreRecord1.setGameCost(scoreRecord.getGameCost());
                yjScoreRecord1.setIsHelpRecord(scoreRecord.getIsHelpRecord());
                yjScoreRecord1.setUpdateBy(scoreRecord.getUpdateBy());
                yjScoreRecordService.updateScoreInfo(yjScoreRecord1);
            }
        }

        logger.info("saveScore:{}:保存分数结束：{}", openId, interval.intervalRestart());
        ajaxJson.setSuccess(true);
        ajaxJson.setMsg("保存成功，跳转下一局，等待玩家结算");
        ajaxJson.setBody(linkedHashMap);
        try {
            if (!UserMsgSocket.webSocketTable.isEmpty() && UserMsgSocket.webSocketTable.row(openId).get(roomFlag) != null) {
                UserMsgSocket.webSocketTable.row(openId).get(roomFlag).getValue1().sendMessage();
            }

        } catch (IOException e) {
            e.printStackTrace();
            logger.error("saveScore异常：", e);
        }
        return ajaxJson;
    }


    @ResponseBody
    @PostMapping(value = "saveScoreUnified")
    public AjaxJson saveScoreUnified(HttpServletRequest request, @RequestBody Dict param) throws IOException {
        TimeInterval interval = DateUtil.timer();
        TimeInterval intervalTest = DateUtil.timer();
        final LinkedHashMap<String, Object> linkedHashMap = Maps.newLinkedHashMap();
        AjaxJson ajaxJson = new AjaxJson();
        String openId = param.getStr("openId");
        logger.info("saveScore:{}:保存分数开始", openId);
        //参数：房间唯一标识，房间号，牌局，台费，【{玩家，积分}】
        if (StringUtils.isBlank(openId)) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("用户为空");
            return ajaxJson;
        }
        //玩家和自己的唯一键不一样为帮记
        final String gamesCount = StrUtil.isBlank(param.getStr("gamesCount")) ? null : param.getStr("gamesCount");
        if (gamesCount == null || !NumberUtil.isNumber(gamesCount)) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("牌局数异常");
            return ajaxJson;
        }
        linkedHashMap.put("gamesCount", NumberUtil.isNumber(gamesCount) ? NumberUtil.toInt(gamesCount) : null);
        AtomicReference<String> roomNum = new AtomicReference<>();
        final String roomFlag = StrUtil.isBlank(param.getStr("roomFlag")) ? null : param.getStr("roomFlag");
        if (StringUtils.isBlank(roomFlag)) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("房间参数为空");
            return ajaxJson;
        }
        //查询房间玩家
        final Map<String, String> roomUsers = yjRoomUserMapper.findByRoomFlagAndIsOut("0", roomFlag)
                .stream()
                .peek(v1 -> {
                    roomNum.set(v1.getRoomNum());
                })
                .collect(LinkedHashMap::new, (m, v) -> m.put(v.getRoomUser(), null), LinkedHashMap::putAll);
        if (roomUsers.isEmpty()) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("房间不存在");
            return ajaxJson;
        }
        logger.info("saveScore:{}: 到查询房间用时：{}", openId, intervalTest.intervalRestart());
        String gameCost = StrUtil.isBlank(param.getStr("gameCost")) ? "0" : param.getStr("gameCost");
        final List<YjScoreRecord> yjScoreRecords = (param.get("infos") == null ? null : Convert.toList(Dict.class, param.get("infos")))
                .stream()
                .map(v1 -> {
                    YjScoreRecord yjScoreRecord = new YjScoreRecord();
                    yjScoreRecord.setRoomNum(roomNum.get());
                    yjScoreRecord.setRoomFlag(roomFlag);
                    yjScoreRecord.setRoomUser(v1.getStr("roomUser"));
                    if (openId.equals(v1.get("roomUser"))) {
                        yjScoreRecord.setGameCost(gameCost);
                    } else {
                        yjScoreRecord.setGameCost("0");
                    }
                    yjScoreRecord.setScore(StrUtil.isBlank(v1.getStr("score")) ? "0" : v1.getStr("score"));
                    yjScoreRecord.setGamesCount(gamesCount);
                    return yjScoreRecord;
                })
                .collect(Collectors.toList());
        if (yjScoreRecords.stream()
                .filter(v1 -> StringUtils.isBlank(v1.getRoomUser()) || !roomUsers.containsKey(v1.getRoomUser()))
                .filter(v1 -> !NumberUtil.isNumber(v1.getScore()))
                .filter(v1 -> !NumberUtil.isNumber(v1.getGameCost()))
                .findAny()
                .orElse(null) != null) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("提交参数异常");
            return ajaxJson;
        }
        yjScoreRecords.forEach(v1 -> roomUsers.put(v1.getRoomUser(), NumberUtil.toString(NumberUtil.toInt(v1.getScore()) + NumberUtil.toInt(v1.getGameCost()))));
        final List<YjScoreRecord> saveInfos = yjScoreRecordService.findByRoomFlagAndGamesCount(roomFlag, gamesCount)
                .stream()
                .peek(v1 -> {
                    if (roomUsers.get(v1.getRoomUser()) == null) {
                        roomUsers.put(v1.getRoomUser(), NumberUtil.toString(NumberUtil.toInt(v1.getScore()) + NumberUtil.toInt(v1.getGameCost())));
                    }
                })
                .collect(Collectors.toList());
        logger.info("saveScore:{}:到查询得分用时：{}", openId, intervalTest.intervalRestart());
        if (roomUsers.containsValue(null)) {
            logger.info("数据还未填完");
        } else {
            final int sum = roomUsers.values().stream().mapToInt(NumberUtil::toInt).sum();
            if (sum != 0) {
                ajaxJson.setSuccess(false);
                ajaxJson.setErrorCode("0");
                ajaxJson.setMsg(String.valueOf(sum));
                return ajaxJson;
            } else {
                yjRoomUserMapper.updateEndGamesCountByRoomFlag(roomFlag, StrUtil.isBlank(gamesCount) ? "1" : gamesCount);
                linkedHashMap.put("gamesCount", NumberUtil.isNumber(gamesCount) ? NumberUtil.toInt(gamesCount) + 1 : null);
                yjScoreRecordService.socketPutNextGame(openId, roomFlag, NumberUtil.toInt(gamesCount) + 1);
            }
        }
        for (YjScoreRecord scoreRecord : yjScoreRecords) {
            final YjScoreRecord yjScoreRecord1 = saveInfos.stream().filter(v1 -> scoreRecord.getRoomUser().equals(v1.getRoomUser())).findAny().orElse(null);
            //登录的不等于记录的，为带记
            scoreRecord.setIsHelpRecord(1);
            scoreRecord.setUpdateBy(new User(scoreRecord.getRoomUser()));
            if (yjScoreRecord1 == null) {
                yjScoreRecordService.save(scoreRecord);
            } else {
                yjScoreRecord1.setScore(scoreRecord.getScore());
                yjScoreRecord1.setGameCost(scoreRecord.getGameCost());
                yjScoreRecord1.setIsHelpRecord(scoreRecord.getIsHelpRecord());
                yjScoreRecord1.setUpdateBy(scoreRecord.getUpdateBy());
                yjScoreRecordService.updateScoreInfo(yjScoreRecord1);
            }
        }
        logger.info("saveScore:{}:保存分数结束：{}", openId, interval.intervalRestart());
        ajaxJson.setSuccess(true);
        ajaxJson.setMsg("保存成功，跳转下一局，等待玩家结算");
        ajaxJson.setBody(linkedHashMap);
        try {
            if (!UserMsgSocket.webSocketTable.isEmpty() && UserMsgSocket.webSocketTable.row(openId).get(roomFlag) != null) {
                UserMsgSocket.webSocketTable.row(openId).get(roomFlag).getValue1().sendMessage();
            }

        } catch (IOException e) {
            e.printStackTrace();
            logger.error("saveScore异常：", e);
        }
        return ajaxJson;
    }

    /**
     * 获取房间进行到第几局
     *
     * @param openId
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "curGamesNum")
    public AjaxJson curGamesNum(String openId, HttpServletRequest request) {
        AjaxJson ajaxJson = new AjaxJson();
        final String roomFlag = request.getParameter("roomFlag");
        if (StringUtils.isBlank(roomFlag)) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("房间参数为空");
            return ajaxJson;
        }
//
//        final Map<String, String> roomUsers = yjRoomUserMapper.findByRoomFlagAndIsOut("0", roomFlag).stream()
//                .collect(LinkedHashMap::new, (m, v) -> m.put(v.getRoomUser(), null), LinkedHashMap::putAll);

        /*  final YJRoomUser yjRoomUser = yjRoomUserMapper.findByRoomFlagAndIsOut("0", roomFlag).stream().findAny().orElse(null);
         */
//


        final LinkedHashMap<String, Object> linkedHashMap = Maps.newLinkedHashMap();
//        if (yjScoreRecords.isEmpty()) {
//            linkedHashMap.put("gamesCount", "1");
//        } else {
//            yjScoreRecords.forEach(v1 -> roomUsers.put(v1.getRoomUser(), NumberUtil.toString(NumberUtil.toInt(v1.getScore()) + NumberUtil.toInt(v1.getGameCost()))));
//            if (roomUsers.values().contains(null)) {
//                linkedHashMap.put("gamesCount", yjScoreRecords.stream().findFirst().get().getGamesCount());
//            } else {
//                final int sum = roomUsers.values().stream().mapToInt(value -> NumberUtil.toInt(value)).sum();
//                if (sum != 0) {
//                    linkedHashMap.put("gamesCount", yjScoreRecords.stream().findFirst().get().getGamesCount());
//                } else {
//                    linkedHashMap.put("gamesCount", NumberUtil.toInt(yjScoreRecords.stream().findFirst().get().getGamesCount()) + 1);
//                }
//            }
//        }

        Integer integer = yjScoreRecordService.maxCurGamesNum(roomFlag);
        linkedHashMap.put("gamesCount", integer != null ? integer : 0);
        ajaxJson.setSuccess(true);
        ajaxJson.setMsg("获取成功");
        ajaxJson.setBody(linkedHashMap);
        return ajaxJson;
    }

    /**
     * 发送帮记
     *
     * @param openId
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "helpNotesSend")
    public AjaxJson helpNotesSend(String openId, HttpServletRequest request) throws IOException {
        AjaxJson ajaxJson = new AjaxJson();
        final String roomFlag = request.getParameter("roomFlag");
        if (StringUtils.isBlank(roomFlag)) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("房间参数为空");
            return ajaxJson;
        }
        String helpNotesId = request.getParameter("helpNotesId");
        if (StrUtil.isBlank(helpNotesId)) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("帮记用户为空");
            return ajaxJson;
        }
        final List<YsUser> collect = yjRoomUserMapper.findUserInfoByRoomFlag(roomFlag);
        final YsUser helpNotesUser = collect.stream().filter(v1 -> v1.getOpenid().equals(helpNotesId)).findAny().orElse(null);
        final YsUser roomUser = collect.stream().filter(v1 -> v1.getOpenid().equals(openId)).findAny().orElse(null);
        if (helpNotesUser == null || roomUser == null) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("用户没有进入本房间");
            return ajaxJson;
        }

        final Pair<String, String> keyCache = Pair.with(helpNotesId, roomFlag);
        //不存在帮记，就添加状态为0
        if (helpNotesCache.get(keyCache) == null) {
            Table<String, YsUser, Integer> table = HashBasedTable.create();
            table.put(roomUser.getOpenid(), roomUser, 0);
            helpNotesCache.put(keyCache, CollUtil.newLinkedList(table));
        } else {
            //有的话，添加
            final List<Table<String, YsUser, Integer>> pairList = helpNotesCache.get(keyCache);
            final Table<String, YsUser, Integer> valueCache = HashBasedTable.create();
            valueCache.put(roomUser.getOpenid(), roomUser, 0);
            if (pairList.stream().filter(v1 -> roomUser.getOpenid().equals(v1.rowKeySet().stream().findFirst().orElse(null))).findAny().orElse(null) == null) {
                pairList.add(valueCache);
            }
        }
        final TimeInterval timer = DateUtil.timer();
        //推送帮记
        yjScoreRecordService.socketPutHelpRecord(helpNotesId, openId, roomFlag, true);
        Table<String, YsUser, Integer> pair;
        do {
            pair = helpNotesCache.get(keyCache).stream().filter(v1 -> openId.equals(v1.rowKeySet().stream().findFirst().orElse(null))).findAny().orElse(null);
            if (pair == null) {
                ajaxJson.setSuccess(false);
                ajaxJson.setErrorCode("0");
                ajaxJson.setMsg("不存在了");
                return ajaxJson;
            } else if (timer.intervalSecond() > 30) {
                helpNotesCache.get(keyCache).remove(pair);
                ajaxJson.setSuccess(false);
                ajaxJson.setErrorCode("0");
                ajaxJson.setMsg("超时");
                return ajaxJson;
            } else if (pair.row(roomUser.getOpenid()).values().stream().findFirst().orElse(0).equals(0)) {
                ThreadUtil.sleep(500);
            } else {
                break;
            }
        } while (pair == null || pair.row(roomUser.getOpenid()).values().stream().findFirst().orElse(0).equals(0));

        //别人不同意,我需要删除缓存
        if (pair.row(roomUser.getOpenid()).values().stream().findFirst().orElse(0).equals(2)) {
            helpNotesCache.get(keyCache).remove(pair);
        }
        final LinkedHashMap<String, Object> linkedHashMap = Maps.newLinkedHashMap();
        final Integer integer = pair.row(pair.rowKeySet().stream().findFirst().orElse(null)).values().stream().findFirst().orElse(0);
        linkedHashMap.put("isOk", integer.equals(1) ? true : false);
        ajaxJson.setBody(linkedHashMap);
        ajaxJson.setSuccess(true);
        ajaxJson.setMsg("请求成功");
        return ajaxJson;
    }

    /**
     * 确定帮记
     *
     * @return
     */
    @ResponseBody
    @PostMapping(value = "helpNotesVerify")
    public AjaxJson helpNotesVerify(@RequestBody Map<String, Object> param) {
        AjaxJson ajaxJson = new AjaxJson();
        String openId = (String) param.get("openId");
        if (StringUtils.isBlank(openId)) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("用户为空");
            return ajaxJson;
        }
        final String roomFlag = (String) param.get("roomFlag");
        if (StringUtils.isBlank(roomFlag)) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("房间参数为空");
            return ajaxJson;
        }
        final Boolean isOk = (Boolean) param.get("isOk");
        final List<String> helpNotesIds = param.get("helpNotesId") != null ? Arrays.asList(param.get("helpNotesId").toString().split(",|,")) : new ArrayList<>();
        final List<Table<String, YsUser, Integer>> pairList = helpNotesCache.get(Pair.with(openId, roomFlag));
        final LinkedHashMap<String, Object> linkedHashMap = Maps.newLinkedHashMap();
        if (pairList != null && !pairList.isEmpty()) {
            //存在就是确认是否帮记
            if (!helpNotesIds.isEmpty()) {
                for (String helpNotesId : helpNotesIds) {
                    final Table<String, YsUser, Integer> pair = pairList.stream().filter(v1 -> helpNotesId.equals(v1.rowKeySet().stream().findFirst().orElse(null))).findAny().orElse(null);
                    if (pair != null) {
                        if (isOk != null) {
                            pair.put(helpNotesId, pair.row(helpNotesId).keySet().stream().findFirst().orElse(null), isOk ? 1 : 2);
                        }
                    }
                }
            } else {
                List<YsUser> ysUserList = new ArrayList<>();
                List<Table<String, YsUser, Integer>> removeList = new ArrayList<>();
                pairList.forEach(v1 -> {
                    final String row = v1.rowKeySet().stream().findFirst().orElse(null);
                    final Integer integer = v1.get(row, v1.row(row).keySet().stream().findFirst().orElse(null));
                    if (!v1.isEmpty() && integer.equals(0)) {
                        ysUserList.add(v1.row(row).keySet().stream().findFirst().orElse(null));
                    } else if (!v1.isEmpty() && integer.equals(3)) {
                        removeList.add(v1);
                    }
                });
                pairList.removeAll(removeList);
                linkedHashMap.put("users", ysUserList);
                linkedHashMap.put("removeUsers", removeList.stream().map(v1 -> v1.row(v1.rowKeySet().stream().findFirst().orElse(null)).keySet().stream().findFirst().orElse(null)).collect(Collectors.toList()));
            }
        }
        ajaxJson.setBody(linkedHashMap);
        ajaxJson.setSuccess(true);
        ajaxJson.setMsg("请求成功");
        return ajaxJson;
    }

    @ResponseBody
    @RequestMapping(value = "helpNotesRemove")
    public AjaxJson helpNotesRemove(String openId, HttpServletRequest request) throws IOException {
        AjaxJson ajaxJson = new AjaxJson();
        final String roomFlag = request.getParameter("roomFlag");
        if (StringUtils.isBlank(roomFlag)) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("房间参数为空");
            return ajaxJson;
        }
        final Iterator<CacheObj<Pair<String, String>, List<Table<String, YsUser, Integer>>>> cacheObjIterator = helpNotesCache.cacheObjIterator();
        while (cacheObjIterator.hasNext()) {
            final CacheObj<Pair<String, String>, List<Table<String, YsUser, Integer>>> next = cacheObjIterator.next();
            final Pair<String, String> key = next.getKey();
            if (key.getValue1().equals(roomFlag)) {
                final List<Table<String, YsUser, Integer>> value = next.getValue();
                final Table<String, YsUser, Integer> objects = value.stream().filter(v1 -> openId.equals(v1.rowKeySet().stream().findFirst().orElse(null))).findAny().orElse(null);
                if (objects != null) {
                    final String row = objects.rowKeySet().stream().findFirst().orElse(null);
                    objects.put(row, objects.row(row).keySet().stream().findFirst().orElse(new YsUser()), 3);
                    yjScoreRecordService.socketPutHelpRecord(key.getValue0(), openId, roomFlag, false);
                }
            }
        }
        ajaxJson.setSuccess(true);
        ajaxJson.setMsg("请求成功");
        return ajaxJson;
    }

    @ResponseBody
    @RequestMapping(value = "helpNotesExist")
    public AjaxJson helpNotesExist(String openId, HttpServletRequest request) {
        AjaxJson ajaxJson = new AjaxJson();
        final String roomFlag = request.getParameter("roomFlag");
        if (StringUtils.isBlank(roomFlag)) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("房间参数为空");
            return ajaxJson;
        }
        final List<YsUser> collect = yjRoomUserMapper.findUserInfoByRoomFlag(roomFlag);
        List<YsUser> list = new LinkedList<>();
        final YsUser ysUser = collect.stream().filter(v1 -> v1.getOpenid().equals(openId)).findAny().orElse(null);
        if (ysUser == null) {
            ajaxJson.setSuccess(false);
            ajaxJson.setErrorCode("0");
            ajaxJson.setMsg("用户不存在或退出房间");
            return ajaxJson;
        }
        list.add(ysUser);
        final List<Table<String, YsUser, Integer>> tables = helpNotesCache.get(Pair.with(openId, roomFlag));
        if (tables != null && !tables.isEmpty()) {
            tables.stream().forEach(v1 -> {
                final String row = v1.rowKeySet().stream().findFirst().orElse(null);
                final Integer integer = v1.get(row, v1.row(row).keySet().stream().findFirst().orElse(null));
                if (integer.equals(1)) {
                    list.add(v1.row(row).keySet().stream().findFirst().orElse(null));
                }
            });
        }
        boolean beingHelped = false;
        if (!helpNotesCache.isEmpty()) {
            final Iterator<CacheObj<Pair<String, String>, List<Table<String, YsUser, Integer>>>> cacheObjIterator = helpNotesCache.cacheObjIterator();
            while (cacheObjIterator.hasNext()) {
                final CacheObj<Pair<String, String>, List<Table<String, YsUser, Integer>>> next = cacheObjIterator.next();
                if (next.getValue().stream().findFirst().isPresent() && next.getValue().stream().findFirst().get().row(openId) != null) {
                    final Integer integer = next.getValue().stream().findFirst().get().row(openId).values().stream().findFirst().orElse(-1);
                    if (integer.equals(1)) {
                        beingHelped = true;
                        break;
                    }
                }
            }
        }
        final LinkedHashMap<String, Object> linkedHashMap = Maps.newLinkedHashMap();
        linkedHashMap.put("users", list);
        linkedHashMap.put("beingHelped", beingHelped);
        ajaxJson.setBody(linkedHashMap);
        ajaxJson.setSuccess(true);
        ajaxJson.setMsg("请求成功");
        return ajaxJson;
    }

    @ResponseBody
    @RequestMapping(value = "scoringDetails")
    public AjaxJson scoringDetails(String openId, Integer pageSize, Integer pageNum, HttpServletRequest request) {
        AjaxJson ajaxJson = new AjaxJson();
        pageSize = pageSize == null ? 10 : pageSize;
        pageNum = pageNum == null ? 1 : pageNum;
        List<String> roomFlags = yjRoomUserMapper.findRoomFlagByRoomUser(openId, (pageNum - 1) * pageSize, pageSize);
        if (roomFlags == null || roomFlags.isEmpty()) {
            ajaxJson.setSuccess(true);
            ajaxJson.setMsg("请求成功");
            return ajaxJson;
        }
        final Integer count = yjRoomUserMapper.findRoomFlagCountByRoomUser(openId);
        List<YjScoreRecord> list = yjRoomUserMapper.findScoringDetails(roomFlags.stream().map(v -> StrUtil.format("'{}'", v)).collect(Collectors.joining(",")));
        Map<String, String> sumMap = new HashMap<>();
        Map<String, Tuple> userMap = new HashMap<>();
        Map<String, Table<String, Integer, Object>> map = new HashMap<>();
        if (!list.isEmpty()) {
            for (YjScoreRecord yjScoreRecord : list) {
                final String key = StrUtil.format("{}_{}", yjScoreRecord.getRoomFlag(), yjScoreRecord.getRoomNum());
                if (map.get(key) == null) {
                    map.put(key, HashBasedTable.create());
                }
                final Table<String, Integer, Object> table = map.get(key);
                table.put(yjScoreRecord.getRoomUser(), NumberUtil.toInt(yjScoreRecord.getGamesCount()), NumberUtil.toInt(yjScoreRecord.getScore()));
                if (yjScoreRecord.getGameCost() != null && !"0".equals(yjScoreRecord.getGameCost())) {
                    Integer score = (Integer) table.get("#台费#", NumberUtil.toInt(yjScoreRecord.getGamesCount()));
                    if (score == null) {
                        score = 0;
                    }
                    table.put("#台费#", NumberUtil.toInt(yjScoreRecord.getGamesCount()), NumberUtil.toInt(yjScoreRecord.getGameCost()) + score);
                } else {
                    Integer score = (Integer) table.get("#台费#", NumberUtil.toInt(yjScoreRecord.getGamesCount()));
                    if (score == null) {
                        score = 0;
                    }
                    table.put("#台费#", NumberUtil.toInt(yjScoreRecord.getGamesCount()), 0 + score);
                }
                //时间
                table.put("#时间#", NumberUtil.toInt(yjScoreRecord.getGamesCount()), DateUtil.format(yjScoreRecord.getCreateDate(), "yyyy-MM-dd HH:mm:ss"));
                //房间对局数
                if (sumMap.get(yjScoreRecord.getRoomFlag()) == null) {
                    sumMap.put(yjScoreRecord.getRoomFlag(), yjScoreRecord.getGamesCount());
                } else {
                    sumMap.put(yjScoreRecord.getRoomFlag(), String.valueOf(Math.max(NumberUtil.toInt(sumMap.get(yjScoreRecord.getRoomFlag())), NumberUtil.toInt(yjScoreRecord.getGamesCount()))));
                }
                if (userMap.get(yjScoreRecord.getRoomUser()) == null) {
                    userMap.put(yjScoreRecord.getRoomUser(), new Tuple(yjScoreRecord.getUserName(), yjScoreRecord.getUserUrl()));
                }
            }
        }
        for (String key : map.keySet()) {
            final Dict flagInfo = Dict.create().set("roomFlag", key.split("_")[0]).set("roomNum", key.split("_")[1]);
            final Table<String, Integer, Object> table = map.get(key);
            if (sumMap.get(flagInfo.getStr("roomFlag")) != null) {
                table.rowKeySet().stream().forEach(roomUser -> {
                    final Map<Integer, Object> row = table.row(roomUser);
                    if (!"#时间#".equals(roomUser)) {
                        for (int i = 1; i <= NumberUtil.toInt(sumMap.get(flagInfo.getStr("roomFlag"))); i++) {
                            if (row.get(i) == null) {
                                row.put(i, 0);
                            }
                        }
                    }
                });
            }
        }
        List<Dict> data = new ArrayList<>();
        map.keySet().forEach(v1 -> {
            final Dict dict = Dict.create().set("roomFlag", v1.split("_")[0]).set("roomNum", v1.split("_")[1]);
            List<Dict> userInfo = new ArrayList<>();
            map.get(v1).rowKeySet().forEach(v2 -> {
                if (v2.equals("#台费#") || v2.equals("#时间#")) {
                    return;
                }
                final TreeMap<Integer, Object> treeMap = new TreeMap<>(Comparator.reverseOrder());
                treeMap.putAll(map.get(v1).row(v2));
                final List<Integer> collect = treeMap.values().stream().map(v -> NumberUtil.toInt(v.toString())).filter(v -> v >= 0).collect(Collectors.toList());

                Map<String, String> userName = new HashMap<>();
                if (Objects.isNull(userMap.get(v2).get(0)) || userMap.get(v2).get(0).toString() == "") {
                    YJRoomUser yjRoomUser = new YJRoomUser();
                    yjRoomUser.setRoomUser(v2);
                    List<YJRoomUser> allList = yjRoomUserMapper.findListUserName(yjRoomUser);
                    if (Objects.nonNull(allList) && !allList.isEmpty()) {
                        for (YJRoomUser roomUser : allList) {
                            if (Objects.nonNull(roomUser.getUserName())) {
                                userName.put(userMap.get(v2).get(0), roomUser.getUserName());
                            }
                        }

                    }
                }


                userInfo.add(Dict.create()
                        .set("roomUser", v2)
                        .set("userName", Objects.isNull(userMap.get(v2).get(0)) ? userName.get(userMap.get(v2).get(0)) : userMap.get(v2).get(0))
                        .set("userUrl", Objects.isNull(userMap.get(v2).get(1)) ? userName.get(userMap.get(v2).get(0)) : userMap.get(v2).get(1))
                        .set("victory", new DecimalFormat("0.00%").format(cn.hutool.core.util.NumberUtil.div(collect.size(), treeMap.size())))
                        .set("sum", treeMap.keySet().stream().mapToInt(gamesCount -> NumberUtil.toInt(treeMap.get(gamesCount).toString())).sum()))
                ;
            });

            final TreeMap<Integer, Object> date = new TreeMap<>(Comparator.reverseOrder());
            date.putAll(map.get(v1).row("#时间#"));
            final TreeMap<Integer, Object> gameCost = new TreeMap<>(Comparator.reverseOrder());
            gameCost.putAll(map.get(v1).row("#台费#"));
            dict.set("totalGameCost", gameCost.values().stream().mapToInt(v -> NumberUtil.toInt(v.toString())).sum()).set("totalDate", date.values().stream().findFirst().orElse(null)).set("userInfo", userInfo);
            data.add(dict);
        });

        Collections.sort(data, new Comparator<Dict>() {
            @Override
            public int compare(Dict o1, Dict o2) {
                if (DateUtil.parse(o1.getStr("totalDate")).getTime() > DateUtil.parse(o2.getStr("totalDate")).getTime()) {
                    return -1;
                } else if (DateUtil.parse(o1.getStr("totalDate")).getTime() < DateUtil.parse(o2.getStr("totalDate")).getTime()) {
                    return 1;
                } else {
                    return 0;
                }
            }
        });

        final LinkedHashMap<String, Object> linkedHashMap = Maps.newLinkedHashMap();
        linkedHashMap.put("data", data);
        linkedHashMap.put("pageNum", pageNum);
        linkedHashMap.put("pageCount", PageUtil.totalPage(count, pageSize));
        ajaxJson.setBody(linkedHashMap);
        ajaxJson.setSuccess(true);
        ajaxJson.setMsg("请求成功");
        return ajaxJson;
    }


    public AjaxJson test(String openId, Integer pageSize, Integer pageNum) {
        final AjaxJson ajaxJson = new AjaxJson();
        ajaxJson.setMsg("触发测试");
        return ajaxJson;
    }

    public static void main(String[] args) {
        Pair<String, String> pair1 = Pair.with("1", "2");
        Pair<String, String> pair2 = Pair.with("1", "2");

        System.out.println(pair1.equals(pair2));
    }
}
